<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"wan-lei8.gitee.io","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
  </script>

  <meta name="description" content="1、查询SQL尽量不要使用select *，而是select具体字段。">
<meta property="og:type" content="article">
<meta property="og:title" content="书写高质量SQL的30条建议">
<meta property="og:url" content="https://wan-lei8.gitee.io/2022/03/10/%E4%B9%A6%E5%86%99%E9%AB%98%E8%B4%A8%E9%87%8FSQL%E7%9A%8430%E6%9D%A1%E5%BB%BA%E8%AE%AE/index.html">
<meta property="og:site_name" content="程序员西桐">
<meta property="og:description" content="1、查询SQL尽量不要使用select *，而是select具体字段。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPOfQNzXNFy4W6W1ibKwiaLnfpNREWUgYQ0GnGe5aaUh92orkPCVg5yicgQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScP4URibxzL4mNibbtlcmPn4N9wUzCdOQdxQBtiasiaUVpMiazRicQlaGhlJx3A/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPk17jU8xhWNmpcKFsFhhIak2nKHZ03LGN76kJF64JichINNR2ojjUw2Q/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPVdZeVj4YAovZUqZskZLYCXyGJrJkR5d0ImCDEznlbIhMKXCz0CSFxg/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPlJ2mfzTJ9N32rcl3ZRU392Z3AZeRdKtibHQOIYic2xLfF2Abx9mwgEzw/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPClMpib1ian00BHyyV7XOgjLvNPk5mklEs0qb4YMGFVpFWqvFRemx3hicQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPFPF9jydclv7t2eafvxjloCEeZsuxuTOnmNicbyjHHGE4hicu5lyeVstQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPkbthLDAYRbB1ET2VRFbGkPeiaEJia6DKfcgxdbhLpcwLQMgicrytibLibLA/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPoq4wU2qLib4loaRvsOVAdVVsb8rGKTXVnUgsmL3kzQ1R1eeCqy28Icw/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPtMkt6DrrZhxQKuU1QwToYz8FZZrx0uHq8BjnJxPuzlbvibfGWsRPqPg/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScP9gYW4ElfM1ZEcp26YvibUCV68iaz0ibpTeHx2IR5V7RjlaC9ibmTT8tyOQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPrd8KKXrrphmjew1cBjl1zmDjicChzuGoy2fBHOK3Ucwf1eib2ibM9JjpQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPGPH2UWz7B52xGG4qnwzjvm7zylGzqO6ibaOQRl2aIRbZItuSAmib6E6Q/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPpGaIXGyl6sM870VLHmefPm11nHeFVXy7jDkDPcn4udva28610PZazQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScP5ddsPEgH1IyaibqqSqlBZFWdvqQW0gSyO6GTd0nUrwnIQiaRn7Q9QpcQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPvyD4fPDXTdMUfegkNnyNdP8QDJrbMIx9HSeSCjp9XMicfD4NM6ZyTLQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPBvAt3ibwlniaMrZssCsPJ3QrhXW0tzbEMow5Fzov7RSKagxpQt678x0Q/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="og:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPyibKRjWdCqIgia1UehM2ua0B1n4MtHJgib9sgnhbH6rS5segZSXRMVA9g/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">
<meta property="article:published_time" content="2022-03-10T06:25:33.000Z">
<meta property="article:modified_time" content="2022-03-10T06:26:42.314Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPOfQNzXNFy4W6W1ibKwiaLnfpNREWUgYQ0GnGe5aaUh92orkPCVg5yicgQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1">

<link rel="canonical" href="https://wan-lei8.gitee.io/2022/03/10/%E4%B9%A6%E5%86%99%E9%AB%98%E8%B4%A8%E9%87%8FSQL%E7%9A%8430%E6%9D%A1%E5%BB%BA%E8%AE%AE/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>书写高质量SQL的30条建议 | 程序员西桐</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">程序员西桐</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">但行好事，莫问前程</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://wan-lei8.gitee.io/2022/03/10/%E4%B9%A6%E5%86%99%E9%AB%98%E8%B4%A8%E9%87%8FSQL%E7%9A%8430%E6%9D%A1%E5%BB%BA%E8%AE%AE/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="程序员西桐">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          书写高质量SQL的30条建议
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2022-03-10 14:25:33 / 修改时间：14:26:42" itemprop="dateCreated datePublished" datetime="2022-03-10T14:25:33+08:00">2022-03-10</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h3 id="1、查询SQL尽量不要使用select-，而是select具体字段。"><a href="#1、查询SQL尽量不要使用select-，而是select具体字段。" class="headerlink" title="1、查询SQL尽量不要使用select *，而是select具体字段。"></a>1、查询SQL尽量不要使用select *，而是select具体字段。</h3><span id="more"></span>

<p>反例子：</p>
<figure class="highlight axapta"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> * <span class="keyword">from</span> employee;</span><br></pre></td></tr></table></figure>

<p>正例子：</p>
<figure class="highlight applescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">select <span class="built_in">id</span>，<span class="built_in">name</span> <span class="keyword">from</span> employee;</span><br></pre></td></tr></table></figure>

<p>理由：</p>
<ul>
<li>只取需要的字段，节省资源、减少网络开销。</li>
<li>select * 进行查询时，很可能就不会使用到覆盖索引了，就会造成回表查询。</li>
</ul>
<h3 id="2、如果知道查询结果只有一条或者只要最大-最小一条记录，建议用limit-1"><a href="#2、如果知道查询结果只有一条或者只要最大-最小一条记录，建议用limit-1" class="headerlink" title="2、如果知道查询结果只有一条或者只要最大/最小一条记录，建议用limit 1"></a>2、如果知道查询结果只有一条或者只要最大/最小一条记录，建议用limit 1</h3><p>假设现在有employee员工表，要找出一个名字叫jay的人.</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> TABLE <span class="symbol">`employee`</span> (  <span class="symbol">`id`</span> int(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span>,  <span class="symbol">`name`</span> varchar(<span class="number">255</span>) DEFAULT <span class="literal">NULL</span>,  <span class="symbol">`age`</span> int(<span class="number">11</span>) DEFAULT <span class="literal">NULL</span>,  <span class="symbol">`date`</span> datetime DEFAULT <span class="literal">NULL</span>,  <span class="symbol">`sex`</span> int(<span class="number">1</span>) DEFAULT <span class="literal">NULL</span>,  <span class="keyword">PRIMARY</span> <span class="keyword">KEY</span> (<span class="symbol">`id`</span>)) ENGINE=InnoDB DEFAULT CHARSET=utf8;</span><br></pre></td></tr></table></figure>

<p>反例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> id，<span class="type">name</span> <span class="keyword">from</span> employee <span class="keyword">where</span> <span class="type">name</span>=<span class="string">&#x27;jay&#x27;</span></span><br></pre></td></tr></table></figure>

<p>正例</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> id，<span class="type">name</span> <span class="keyword">from</span> employee <span class="keyword">where</span> <span class="type">name</span>=<span class="string">&#x27;jay&#x27;</span> <span class="keyword">limit</span> <span class="number">1</span>;</span><br></pre></td></tr></table></figure>

<p>理由：</p>
<ul>
<li>加上limit 1后,只要找到了对应的一条记录,就不会继续向下扫描了,效率将会大大提高。</li>
<li>当然，如果name是唯一索引的话，是不必要加上limit 1了，因为limit的存在主要就是为了防止全表扫描，从而提高性能,如果一个语句本身可以预知不用全表扫描，有没有limit ，性能的差别并不大。</li>
</ul>
<h3 id="3、应尽量避免在where子句中使用or来连接条件"><a href="#3、应尽量避免在where子句中使用or来连接条件" class="headerlink" title="3、应尽量避免在where子句中使用or来连接条件"></a>3、应尽量避免在where子句中使用or来连接条件</h3><p>新建一个user表，它有一个普通索引userId，表结构如下：</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> TABLE <span class="symbol">`user`</span> (  <span class="symbol">`id`</span> int(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> AUTO_INCREMENT,  <span class="symbol">`userId`</span> int(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span>,  <span class="symbol">`age`</span> int(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span>,  <span class="symbol">`name`</span> varchar(<span class="number">255</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span>,  <span class="keyword">PRIMARY</span> <span class="keyword">KEY</span> (<span class="symbol">`id`</span>),  <span class="keyword">KEY</span> <span class="symbol">`idx_userId`</span> (<span class="symbol">`userId`</span>)) ENGINE=InnoDB DEFAULT CHARSET=utf8;</span><br></pre></td></tr></table></figure>

<p>假设现在需要查询userid为1或者年龄为18岁的用户，很容易有以下SQL</p>
<p>反例:</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> userid=<span class="number">1</span> <span class="keyword">or</span> age =<span class="number">18</span></span><br></pre></td></tr></table></figure>

<p>正例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">//使用<span class="keyword">union</span> allselect * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> userid=<span class="number">1</span> <span class="keyword">union</span> allselect * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> age = <span class="number">18</span></span><br><span class="line">//或者分开两条<span class="keyword">sql</span>写：<span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> userid=<span class="number">1</span><span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> age = <span class="number">18</span></span><br></pre></td></tr></table></figure>

<p>理由：</p>
<ul>
<li>使用or可能会使索引失效，从而全表扫描。</li>
</ul>
<blockquote>
<p>对于or+没有索引的age这种情况，假设它走了userId的索引，但是走到age查询条件时，它还得全表扫描，也就是需要三步过程：全表扫描+索引扫描+合并 如果它一开始就走全表扫描，直接一遍扫描就完事。mysql是有优化器的，处于效率与成本考虑，遇到or条件，索引可能失效，看起来也合情合理。</p>
</blockquote>
<h3 id="4、优化limit分页"><a href="#4、优化limit分页" class="headerlink" title="4、优化limit分页"></a>4、优化limit分页</h3><p>我们日常做分页需求时，一般会用 limit 实现，但是当偏移量特别大的时候，查询效率就变得低下。</p>
<p>反例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> id，<span class="type">name</span>，age <span class="keyword">from</span> employee <span class="keyword">limit</span> <span class="number">10000</span>，<span class="number">10</span></span><br></pre></td></tr></table></figure>

<p>正例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">//方案一 ：返回上次查询的最大记录(偏移量)<span class="keyword">select</span> id，<span class="type">name</span> <span class="keyword">from</span> employee <span class="keyword">where</span> id&gt;<span class="number">10000</span> <span class="keyword">limit</span> <span class="number">10.</span></span><br><span class="line">//方案二：<span class="keyword">order</span> <span class="keyword">by</span> + 索引<span class="keyword">select</span> id，<span class="type">name</span> <span class="keyword">from</span> employee <span class="keyword">order</span> <span class="keyword">by</span> id  <span class="keyword">limit</span> <span class="number">10000</span>，<span class="number">10</span></span><br><span class="line">//方案三：在业务允许的情况下限制页数：</span><br></pre></td></tr></table></figure>

<p>理由：</p>
<ul>
<li>当偏移量最大的时候，查询效率就会越低，因为Mysql并非是跳过偏移量直接去取后面的数据，而是先把偏移量+要取的条数，然后再把前面偏移量这一段的数据抛弃掉再返回的。</li>
<li>如果使用优化方案一，返回上次最大查询记录（偏移量），这样可以跳过偏移量，效率提升不少。</li>
<li>方案二使用order by+索引，也是可以提高查询效率的。</li>
<li>方案三的话，建议跟业务讨论，有没有必要查这么后的分页啦。因为绝大多数用户都不会往后翻太多页。</li>
</ul>
<h3 id="5、优化你的like语句"><a href="#5、优化你的like语句" class="headerlink" title="5、优化你的like语句"></a>5、优化你的like语句</h3><p>日常开发中，如果用到模糊关键字查询，很容易想到like，但是like很可能让你的索引失效。</p>
<p>反例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> userId，<span class="type">name</span> <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> userId <span class="keyword">like</span> <span class="string">&#x27;%123&#x27;</span>;</span><br></pre></td></tr></table></figure>

<p>正例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> userId，<span class="type">name</span> <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> userId <span class="keyword">like</span> <span class="string">&#x27;123%&#x27;</span>;</span><br></pre></td></tr></table></figure>

<p>理由：</p>
<ul>
<li>把%放前面，并不走索引，如下： <img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPOfQNzXNFy4W6W1ibKwiaLnfpNREWUgYQ0GnGe5aaUh92orkPCVg5yicgQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></li>
<li>把% 放关键字后面，还是会走索引的。如下： <img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScP4URibxzL4mNibbtlcmPn4N9wUzCdOQdxQBtiasiaUVpMiazRicQlaGhlJx3A/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></li>
</ul>
<h3 id="6、使用where条件限定要查询的数据，避免返回多余的行"><a href="#6、使用where条件限定要查询的数据，避免返回多余的行" class="headerlink" title="6、使用where条件限定要查询的数据，避免返回多余的行"></a>6、使用where条件限定要查询的数据，避免返回多余的行</h3><p>假设业务场景是这样：查询某个用户是否是会员。曾经看过老的实现代码是这样。。。</p>
<p>反例：</p>
<figure class="highlight pf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">List<span class="variable">&lt;Long&gt;</span> <span class="keyword">user</span>Ids = sqlMap.queryList(<span class="string">&quot;select userId from user where isVip=1&quot;</span>);boolean isVip = <span class="keyword">user</span>Ids.contains(<span class="keyword">user</span>Id);</span><br></pre></td></tr></table></figure>

<p>正例：</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Long userId = sqlMap.queryObject(&quot;<span class="keyword">select</span> userId <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> userId=<span class="string">&#x27;userId&#x27;</span> <span class="keyword">and</span> isVip=<span class="string">&#x27;1&#x27;</span> <span class="string">&quot;)boolean isVip = userId！=null;</span></span><br></pre></td></tr></table></figure>

<p>理由：</p>
<ul>
<li>需要什么数据，就去查什么数据，避免返回不必要的数据，节省开销。</li>
</ul>
<h3 id="7、尽量避免在索引列上使用mysql的内置函数"><a href="#7、尽量避免在索引列上使用mysql的内置函数" class="headerlink" title="7、尽量避免在索引列上使用mysql的内置函数"></a>7、尽量避免在索引列上使用mysql的内置函数</h3><p>业务需求：查询最近七天内登陆过的用户(假设loginTime加了索引)</p>
<p>反例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> userId,loginTime <span class="keyword">from</span> loginuser <span class="keyword">where</span> Date_ADD(loginTime,<span class="type">Interval</span> <span class="number">7</span> DAY) &gt;=now();</span><br></pre></td></tr></table></figure>

<p>正例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">explain</span>  <span class="keyword">select</span> userId,loginTime <span class="keyword">from</span> loginuser <span class="keyword">where</span>  loginTime &gt;= Date_ADD(NOW(),<span class="type">INTERVAL</span> - <span class="number">7</span> DAY);</span><br></pre></td></tr></table></figure>

<p>理由：</p>
<ul>
<li>索引列上使用mysql的内置函数，索引失效</li>
</ul>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPk17jU8xhWNmpcKFsFhhIak2nKHZ03LGN76kJF64JichINNR2ojjUw2Q/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<ul>
<li>如果索引列不加内置函数，索引还是会走的。 <img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPVdZeVj4YAovZUqZskZLYCXyGJrJkR5d0ImCDEznlbIhMKXCz0CSFxg/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></li>
</ul>
<h3 id="8、应尽量避免在where子句中对字段进行表达式操作，这将导致系统放弃使用索引而进行全表扫"><a href="#8、应尽量避免在where子句中对字段进行表达式操作，这将导致系统放弃使用索引而进行全表扫" class="headerlink" title="8、应尽量避免在where子句中对字段进行表达式操作，这将导致系统放弃使用索引而进行全表扫"></a>8、应尽量避免在where子句中对字段进行表达式操作，这将导致系统放弃使用索引而进行全表扫</h3><p>反例：</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> age<span class="number">-1</span> =<span class="number">10</span>；</span><br></pre></td></tr></table></figure>

<p>正例：</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> age =<span class="number">11</span>；</span><br></pre></td></tr></table></figure>

<p>理由：</p>
<ul>
<li>虽然age加了索引，但是因为对它进行运算，索引直接迷路了。。。 <img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPlJ2mfzTJ9N32rcl3ZRU392Z3AZeRdKtibHQOIYic2xLfF2Abx9mwgEzw/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></li>
</ul>
<h3 id="9、Inner-join-、left-join、right-join，优先使用Inner-join，如果是left-join，左边表结果尽量小"><a href="#9、Inner-join-、left-join、right-join，优先使用Inner-join，如果是left-join，左边表结果尽量小" class="headerlink" title="9、Inner join 、left join、right join，优先使用Inner join，如果是left join，左边表结果尽量小"></a>9、Inner join 、left join、right join，优先使用Inner join，如果是left join，左边表结果尽量小</h3><blockquote>
<ul>
<li>Inner join 内连接，在两张表进行连接查询时，只保留两张表中完全匹配的结果集</li>
<li>left join 在两张表进行连接查询时，会返回左表所有的行，即使在右表中没有匹配的记录。</li>
<li>right join 在两张表进行连接查询时，会返回右表所有的行，即使在左表中没有匹配的记录。</li>
</ul>
</blockquote>
<p>都满足SQL需求的前提下，推荐优先使用Inner join（内连接），如果要使用left join，左边表数据结果尽量小，如果有条件的尽量放到左边处理。</p>
<p>反例:</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">select</span> * from tab<span class="number">1</span> t<span class="number">1</span> left join tab<span class="number">2</span> t<span class="number">2</span>  <span class="literal">on</span> t<span class="number">1</span>.size = t<span class="number">2</span>.size where t<span class="number">1</span>.id&gt;<span class="number">2</span>;</span><br></pre></td></tr></table></figure>

<p>正例：</p>
<figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">select</span> * from (select * from tab<span class="number">1</span> where id &gt;<span class="number">2</span>) t<span class="number">1</span> left join tab<span class="number">2</span> t<span class="number">2</span> <span class="literal">on</span> t<span class="number">1</span>.size = t<span class="number">2</span>.size;</span><br></pre></td></tr></table></figure>

<p>理由：</p>
<ul>
<li>如果inner join是等值连接，或许返回的行数比较少，所以性能相对会好一点。</li>
<li>同理，使用了左连接，左边表数据结果尽量小，条件尽量放到左边处理，意味着返回的行数可能比较少。</li>
</ul>
<h3 id="10、应尽量避免在where子句中使用-或-lt-gt-操作符，否则将引擎放弃使用索引而进行全表扫描。"><a href="#10、应尽量避免在where子句中使用-或-lt-gt-操作符，否则将引擎放弃使用索引而进行全表扫描。" class="headerlink" title="10、应尽量避免在where子句中使用!=或&lt;&gt;操作符，否则将引擎放弃使用索引而进行全表扫描。"></a>10、应尽量避免在where子句中使用!=或&lt;&gt;操作符，否则将引擎放弃使用索引而进行全表扫描。</h3><p>反例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> age,<span class="type">name</span>  <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> age &lt;&gt;<span class="number">18</span>;</span><br></pre></td></tr></table></figure>

<p>正例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">//可以考虑分开两条<span class="keyword">sql</span>写<span class="keyword">select</span> age,<span class="type">name</span>  <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> age &lt;<span class="number">18</span>;<span class="keyword">select</span> age,<span class="type">name</span>  <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> age &gt;<span class="number">18</span>;</span><br></pre></td></tr></table></figure>

<p>理由：</p>
<ul>
<li>使用!=和&lt;&gt;很可能会让索引失效</li>
</ul>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPClMpib1ian00BHyyV7XOgjLvNPk5mklEs0qb4YMGFVpFWqvFRemx3hicQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<h3 id="11、使用联合索引时，注意索引列的顺序，一般遵循最左匹配原则。"><a href="#11、使用联合索引时，注意索引列的顺序，一般遵循最左匹配原则。" class="headerlink" title="11、使用联合索引时，注意索引列的顺序，一般遵循最左匹配原则。"></a>11、使用联合索引时，注意索引列的顺序，一般遵循最左匹配原则。</h3><p>表结构：（有一个联合索引idxuseridage，userId在前，age在后）</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> TABLE <span class="symbol">`user`</span> (  <span class="symbol">`id`</span> int(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> AUTO_INCREMENT,  <span class="symbol">`userId`</span> int(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span>,  <span class="symbol">`age`</span> int(<span class="number">11</span>) DEFAULT <span class="literal">NULL</span>,  <span class="symbol">`name`</span> varchar(<span class="number">255</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span>,  <span class="keyword">PRIMARY</span> <span class="keyword">KEY</span> (<span class="symbol">`id`</span>),  <span class="keyword">KEY</span> <span class="symbol">`idx_userid_age`</span> (<span class="symbol">`userId`</span>,<span class="symbol">`age`</span>) <span class="keyword">USING</span> BTREE) ENGINE=InnoDB AUTO_INCREMENT=<span class="number">2</span> DEFAULT CHARSET=utf8;</span><br></pre></td></tr></table></figure>

<p>反例：</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> age = <span class="number">10</span>;</span><br></pre></td></tr></table></figure>

<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPFPF9jydclv7t2eafvxjloCEeZsuxuTOnmNicbyjHHGE4hicu5lyeVstQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>正例：</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">//符合最左匹配原则<span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> userid=<span class="number">10</span> <span class="keyword">and</span> age =<span class="number">10</span>；//符合最左匹配原则<span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> userid =<span class="number">10</span>;</span><br></pre></td></tr></table></figure>

<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPkbthLDAYRbB1ET2VRFbGkPeiaEJia6DKfcgxdbhLpcwLQMgicrytibLibLA/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPoq4wU2qLib4loaRvsOVAdVVsb8rGKTXVnUgsmL3kzQ1R1eeCqy28Icw/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">理由：</p>
<ul>
<li>当我们创建一个联合索引的时候，如(k1,k2,k3)，相当于创建了（k1）、(k1,k2)和(k1,k2,k3)三个索引，这就是最左匹配原则。</li>
<li>联合索引不满足最左原则，索引一般会失效，但是这个还跟Mysql优化器有关的。</li>
</ul>
<h3 id="12、对查询进行优化，应考虑在where及order-by涉及的列上建立索引，尽量避免全表扫描。"><a href="#12、对查询进行优化，应考虑在where及order-by涉及的列上建立索引，尽量避免全表扫描。" class="headerlink" title="12、对查询进行优化，应考虑在where及order by涉及的列上建立索引，尽量避免全表扫描。"></a>12、对查询进行优化，应考虑在where及order by涉及的列上建立索引，尽量避免全表扫描。</h3><p>反例：</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> address =<span class="string">&#x27;深圳&#x27;</span> <span class="keyword">order</span> <span class="keyword">by</span> age ;</span><br></pre></td></tr></table></figure>

<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPtMkt6DrrZhxQKuU1QwToYz8FZZrx0uHq8BjnJxPuzlbvibfGWsRPqPg/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">正例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">添加索引<span class="keyword">alter</span> <span class="keyword">table</span> <span class="keyword">user</span> <span class="keyword">add</span> <span class="keyword">index</span> idx_address_age (address,age)</span><br></pre></td></tr></table></figure>

<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScP9gYW4ElfM1ZEcp26YvibUCV68iaz0ibpTeHx2IR5V7RjlaC9ibmTT8tyOQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<h3 id="13、如果插入数据过多，考虑批量插入。"><a href="#13、如果插入数据过多，考虑批量插入。" class="headerlink" title="13、如果插入数据过多，考虑批量插入。"></a>13、如果插入数据过多，考虑批量插入。</h3><p>反例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(<span class="keyword">User</span> u :list)&#123; <span class="keyword">INSERT</span> <span class="keyword">into</span> <span class="keyword">user</span>(<span class="type">name</span>,age) <span class="keyword">values</span>(#<span class="type">name</span>#,#age#)&#125;</span><br></pre></td></tr></table></figure>

<p>正例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">//一次<span class="number">500</span>批量插入，分批进行<span class="keyword">insert</span> <span class="keyword">into</span> <span class="keyword">user</span>(<span class="type">name</span>,age) <span class="keyword">values</span>&lt;<span class="keyword">foreach</span> collection=&quot;list&quot; item=&quot;item&quot; <span class="keyword">index</span>=&quot;index&quot; separator=&quot;,&quot;&gt;    (#&#123;item.name&#125;,#&#123;item.age&#125;)&lt;/<span class="keyword">foreach</span>&gt;</span><br></pre></td></tr></table></figure>

<p>理由：</p>
<ul>
<li>批量插入性能好，更加省时间</li>
</ul>
<blockquote>
<p>打个比喻:假如你需要搬一万块砖到楼顶,你有一个电梯,电梯一次可以放适量的砖（最多放500）,你可以选择一次运送一块砖,也可以一次运送500块砖,你觉得哪个时间消耗大?</p>
</blockquote>
<h3 id="14、在适当的时候，使用覆盖索引。"><a href="#14、在适当的时候，使用覆盖索引。" class="headerlink" title="14、在适当的时候，使用覆盖索引。"></a>14、在适当的时候，使用覆盖索引。</h3><p>覆盖索引能够使得你的SQL语句不需要回表，仅仅访问索引就能够得到所有需要的数据，大大提高了查询效率。</p>
<p>反例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">// <span class="keyword">like</span>模糊查询，不走索引了<span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> userid <span class="keyword">like</span> <span class="string">&#x27;%123%&#x27;</span></span><br></pre></td></tr></table></figure>

<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPrd8KKXrrphmjew1cBjl1zmDjicChzuGoy2fBHOK3Ucwf1eib2ibM9JjpQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">正例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">//id为主键，那么为普通索引，即覆盖索引登场了。<span class="keyword">select</span> id,<span class="type">name</span> <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> userid <span class="keyword">like</span> <span class="string">&#x27;%123%&#x27;</span>;</span><br></pre></td></tr></table></figure>

<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPGPH2UWz7B52xGG4qnwzjvm7zylGzqO6ibaOQRl2aIRbZItuSAmib6E6Q/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<h3 id="15、慎用distinct关键字"><a href="#15、慎用distinct关键字" class="headerlink" title="15、慎用distinct关键字"></a>15、慎用distinct关键字</h3><p>distinct 关键字一般用来过滤重复记录，以返回不重复的记录。在查询一个字段或者很少字段的情况下使用时，给查询带来优化效果。但是在字段很多的时候使用，却会大大降低查询效率。</p>
<p>反例：</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="keyword">DISTINCT</span> * <span class="keyword">from</span>  <span class="keyword">user</span>;</span><br></pre></td></tr></table></figure>

<p>正例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> <span class="keyword">DISTINCT</span> <span class="type">name</span> <span class="keyword">from</span> <span class="keyword">user</span>;</span><br></pre></td></tr></table></figure>

<p>理由：</p>
<ul>
<li>带distinct的语句cpu时间和占用时间都高于不带distinct的语句。因为当查询很多字段时，如果使用distinct，数据库引擎就会对数据进行比较，过滤掉重复数据，然而这个比较、过滤的过程会占用系统资源，cpu时间。</li>
</ul>
<h3 id="16、删除冗余和重复索引"><a href="#16、删除冗余和重复索引" class="headerlink" title="16、删除冗余和重复索引"></a>16、删除冗余和重复索引</h3><p>反例：</p>
<figure class="highlight autohotkey"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">KEY `idx_userId` (`userId`)    KEY `idx_userId_age` (`userId`,`age`)</span><br></pre></td></tr></table></figure>

<p>正例:</p>
<figure class="highlight autohotkey"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">//删除userId索引，因为组合索引（A，B）相当于创建了（A）和（A，B）索引  KEY `idx_userId_age` (`userId`,`age`)</span><br></pre></td></tr></table></figure>

<p>理由：</p>
<ul>
<li>重复的索引需要维护，并且优化器在优化查询的时候也需要逐个地进行考虑，这会影响性能的。</li>
</ul>
<h3 id="17、如果数据量较大，优化你的修改-删除语句。"><a href="#17、如果数据量较大，优化你的修改-删除语句。" class="headerlink" title="17、如果数据量较大，优化你的修改/删除语句。"></a>17、如果数据量较大，优化你的修改/删除语句。</h3><p>避免同时修改或删除过多数据，因为会造成cpu利用率过高，从而影响别人对数据库的访问。</p>
<p>反例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">//一次删除<span class="number">10</span>万或者<span class="number">100</span>万+？<span class="keyword">delete</span> <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> id &lt;<span class="number">100000</span>;//或者采用单一循环操作，效率低，时间漫长<span class="keyword">for</span>（<span class="keyword">User</span> <span class="keyword">user</span>：list）&#123;   <span class="keyword">delete</span> <span class="keyword">from</span> <span class="keyword">user</span>； &#125;</span><br></pre></td></tr></table></figure>

<p>正例：</p>
<figure class="highlight xquery"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">//分批进行删除,如每次<span class="number">500</span><span class="keyword">delete</span> user <span class="keyword">where</span><span class="built_in"> id</span>&lt;<span class="number">500</span><span class="keyword">delete</span> product <span class="keyword">where</span><span class="built_in"> id</span>&gt;=<span class="number">500</span> <span class="keyword">and</span><span class="built_in"> id</span>&lt;<span class="number">1000</span>；</span><br></pre></td></tr></table></figure>

<p>理由：</p>
<ul>
<li>一次性删除太多数据，可能会有lock wait timeout exceed的错误，所以建议分批操作。</li>
</ul>
<h3 id="18、where子句中考虑使用默认值代替null。"><a href="#18、where子句中考虑使用默认值代替null。" class="headerlink" title="18、where子句中考虑使用默认值代替null。"></a>18、where子句中考虑使用默认值代替null。</h3><p>反例：</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> age <span class="keyword">is</span> <span class="keyword">not</span> <span class="literal">null</span>;</span><br></pre></td></tr></table></figure>

<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPpGaIXGyl6sM870VLHmefPm11nHeFVXy7jDkDPcn4udva28610PZazQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">正例：</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">//设置0为默认值<span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> age&gt;<span class="number">0</span>;</span><br></pre></td></tr></table></figure>

<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScP5ddsPEgH1IyaibqqSqlBZFWdvqQW0gSyO6GTd0nUrwnIQiaRn7Q9QpcQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">理由：</p>
<ul>
<li>并不是说使用了is null 或者 is not null 就会不走索引了，这个跟mysql版本以及查询成本都有关。</li>
</ul>
<blockquote>
<p>如果mysql优化器发现，走索引比不走索引成本还要高，肯定会放弃索引，这些条件 <code>！=，&gt;isnull，isnotnull</code>经常被认为让索引失效，其实是因为一般情况下，查询的成本高，优化器自动放弃索引的。</p>
</blockquote>
<ul>
<li><h3 id=""><a href="#" class="headerlink" title=""></a></h3><h3 id="如果把null值，换成默认值，很多时候让走索引成为可能，同时，表达意思会相对清晰一点。"><a href="#如果把null值，换成默认值，很多时候让走索引成为可能，同时，表达意思会相对清晰一点。" class="headerlink" title="如果把null值，换成默认值，很多时候让走索引成为可能，同时，表达意思会相对清晰一点。"></a>如果把null值，换成默认值，很多时候让走索引成为可能，同时，表达意思会相对清晰一点。</h3></li>
</ul>
<h3 id="19、不要有超过5个以上的表连接"><a href="#19、不要有超过5个以上的表连接" class="headerlink" title="19、不要有超过5个以上的表连接"></a>19、不要有超过5个以上的表连接</h3><ul>
<li>连表越多，编译的时间和开销也就越大。</li>
<li>把连接表拆开成较小的几个执行，可读性更高。</li>
<li>如果一定需要连接很多表才能得到数据，那么意味着糟糕的设计了。</li>
</ul>
<h3 id="20、exist-amp-in的合理利用"><a href="#20、exist-amp-in的合理利用" class="headerlink" title="20、exist&amp;in的合理利用"></a>20、exist&amp;in的合理利用</h3><p>假设表A表示某企业的员工表，表B表示部门表，查询所有部门的所有员工，很容易有以下SQL:</p>
<figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> * <span class="function"><span class="keyword">from</span> A <span class="keyword">where</span> deptId <span class="title">in</span> (<span class="params"><span class="keyword">select</span> deptId <span class="keyword">from</span> B</span>)</span>;</span><br></pre></td></tr></table></figure>

<p>这样写等价于：</p>
<blockquote>
<p>先查询部门表B</p>
<p>select deptId from B</p>
<p>再由部门deptId，查询A的员工</p>
<p>select * from A where A.deptId = B.deptId</p>
</blockquote>
<p>可以抽象成这样的一个循环：</p>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">List&lt;&gt; resultSet ;    <span class="keyword">for</span>(int <span class="attribute">i</span>=0;i&lt;B.length;i++) &#123;          <span class="keyword">for</span>(int <span class="attribute">j</span>=0;j&lt;A.length;j++) &#123;          <span class="keyword">if</span>(A[i].<span class="attribute">id</span>==B[j].id) &#123;             resultSet.<span class="builtin-name">add</span>(A[i]);             break;          &#125;       &#125;    &#125;</span><br></pre></td></tr></table></figure>

<p>显然，除了使用in，我们也可以用exists实现一样的查询功能，如下：</p>
<figure class="highlight axapta"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> * <span class="keyword">from</span> A <span class="keyword">where</span> <span class="keyword">exists</span> (<span class="keyword">select</span> <span class="number">1</span> <span class="keyword">from</span> B <span class="keyword">where</span> A.deptId = B.deptId);</span><br></pre></td></tr></table></figure>

<p>因为exists查询的理解就是，先执行主查询，获得数据后，再放到子查询中做条件验证，根据验证结果（true或者false），来决定主查询的数据结果是否得意保留。</p>
<p>那么，这样写就等价于：</p>
<blockquote>
<p>select * from A,先从A表做循环</p>
<p>select * from B where A.deptId = B.deptId,再从B表做循环.</p>
</blockquote>
<p>同理，可以抽象成这样一个循环：</p>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">List&lt;&gt; resultSet ;    <span class="keyword">for</span>(int <span class="attribute">i</span>=0;i&lt;A.length;i++) &#123;          <span class="keyword">for</span>(int <span class="attribute">j</span>=0;j&lt;B.length;j++) &#123;          <span class="keyword">if</span>(A[i].<span class="attribute">deptId</span>==B[j].deptId) &#123;             resultSet.<span class="builtin-name">add</span>(A[i]);             break;          &#125;       &#125;    &#125;</span><br></pre></td></tr></table></figure>

<p>数据库最费劲的就是跟程序链接释放。假设链接了两次，每次做上百万次的数据集查询，查完就走，这样就只做了两次；相反建立了上百万次链接，申请链接释放反复重复，这样系统就受不了了。即mysql优化原则，就是小表驱动大表，小的数据集驱动大的数据集，从而让性能更优。</p>
<p>因此，我们要选择最外层循环小的，也就是，如果<strong>B的数据量小于A，适合使用in，如果B的数据量大于A，即适合选择exist</strong>。</p>
<h3 id="21、尽量用union-all替换-union"><a href="#21、尽量用union-all替换-union" class="headerlink" title="21、尽量用union all替换 union"></a>21、尽量用union all替换 union</h3><p>如果检索结果中不会有重复的记录，推荐union all 替换 union。</p>
<p>反例：</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> userid=<span class="number">1</span> <span class="keyword">union</span>  <span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> age = <span class="number">10</span></span><br></pre></td></tr></table></figure>

<p>正例：</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> userid=<span class="number">1</span> <span class="keyword">union</span> allselect * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> age = <span class="number">10</span></span><br></pre></td></tr></table></figure>

<p>理由：</p>
<ul>
<li>如果使用union，不管检索结果有没有重复，都会尝试进行合并，然后在输出最终结果前进行排序。如果已知检索结果没有重复记录，使用union all 代替union，这样会提高效率。</li>
</ul>
<h3 id="22、索引不宜太多，一般5个以内。"><a href="#22、索引不宜太多，一般5个以内。" class="headerlink" title="22、索引不宜太多，一般5个以内。"></a>22、索引不宜太多，一般5个以内。</h3><ul>
<li>索引并不是越多越好，索引虽然提高了查询的效率，但是也降低了插入和更新的效率。</li>
<li>insert或update时有可能会重建索引，所以建索引需要慎重考虑，视具体情况来定。</li>
<li>一个表的索引数最好不要超过5个，若太多需要考虑一些索引是否没有存在的必要。</li>
</ul>
<h3 id="23、尽量使用数字型字段，若只含数值信息的字段尽量不要设计为字符型"><a href="#23、尽量使用数字型字段，若只含数值信息的字段尽量不要设计为字符型" class="headerlink" title="23、尽量使用数字型字段，若只含数值信息的字段尽量不要设计为字符型"></a>23、尽量使用数字型字段，若只含数值信息的字段尽量不要设计为字符型</h3><p>反例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">`king_id` <span class="type">varchar</span>（<span class="number">20</span>） <span class="keyword">NOT</span> <span class="keyword">NULL</span> <span class="keyword">COMMENT</span> <span class="string">&#x27;守护者Id&#x27;</span></span><br></pre></td></tr></table></figure>

<p>正例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">`king_id` <span class="type">int</span>(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="keyword">NULL</span> <span class="keyword">COMMENT</span> <span class="string">&#x27;守护者Id&#x27;</span></span><br></pre></td></tr></table></figure>

<p>理由：</p>
<ul>
<li>相对于数字型字段，字符型会降低查询和连接的性能，并会增加存储开销。</li>
</ul>
<h3 id="24、索引不适合建在有大量重复数据的字段上，如性别这类型数据库字段。"><a href="#24、索引不适合建在有大量重复数据的字段上，如性别这类型数据库字段。" class="headerlink" title="24、索引不适合建在有大量重复数据的字段上，如性别这类型数据库字段。"></a>24、索引不适合建在有大量重复数据的字段上，如性别这类型数据库字段。</h3><p>因为SQL优化器是根据表中数据量来进行查询优化的，如果索引列有大量重复数据，Mysql查询优化器推算发现不走索引的成本更低，很可能就放弃索引了。</p>
<h3 id="25、尽量避免向客户端返回过多数据量。"><a href="#25、尽量避免向客户端返回过多数据量。" class="headerlink" title="25、尽量避免向客户端返回过多数据量。"></a>25、尽量避免向客户端返回过多数据量。</h3><p>假设业务需求是，用户请求查看自己最近一年观看过的直播数据。</p>
<p>反例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">//一次性查询所有数据回来<span class="keyword">select</span> * <span class="keyword">from</span> LivingInfo <span class="keyword">where</span> watchId =useId <span class="keyword">and</span> watchTime &gt;= Date_sub(now(),<span class="type">Interval</span> <span class="number">1</span> Y)</span><br></pre></td></tr></table></figure>

<p>正例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">//分页查询<span class="keyword">select</span> * <span class="keyword">from</span> LivingInfo <span class="keyword">where</span> watchId =useId <span class="keyword">and</span> watchTime&gt;= Date_sub(now(),<span class="type">Interval</span> <span class="number">1</span> Y) <span class="keyword">limit</span> <span class="keyword">offset</span>，pageSize</span><br><span class="line">//如果是前端分页，可以先查询前两百条记录，因为一般用户应该也不会往下翻太多页，<span class="keyword">select</span> * <span class="keyword">from</span> LivingInfo <span class="keyword">where</span> watchId =useId <span class="keyword">and</span> watchTime&gt;= Date_sub(now(),<span class="type">Interval</span> <span class="number">1</span> Y) <span class="keyword">limit</span> <span class="number">200</span> ;</span><br></pre></td></tr></table></figure>

<h3 id="26、当在SQL语句中连接多个表时-请使用表的别名，并把别名前缀于每一列上，这样语义更加清晰。"><a href="#26、当在SQL语句中连接多个表时-请使用表的别名，并把别名前缀于每一列上，这样语义更加清晰。" class="headerlink" title="26、当在SQL语句中连接多个表时,请使用表的别名，并把别名前缀于每一列上，这样语义更加清晰。"></a>26、当在SQL语句中连接多个表时,请使用表的别名，并把别名前缀于每一列上，这样语义更加清晰。</h3><p>反例：</p>
<figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">select<span class="operator">  * </span>from A innerjoin B on <span class="module-access"><span class="module"><span class="identifier">A</span>.</span></span>deptId = <span class="module-access"><span class="module"><span class="identifier">B</span>.</span></span>deptId;</span><br></pre></td></tr></table></figure>

<p>正例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span>  memeber.name,deptment.deptName <span class="keyword">from</span> A member innerjoin B deptment <span class="keyword">on</span> member.deptId = deptment.deptId;</span><br></pre></td></tr></table></figure>

<h3 id="27、尽可能使用varchar-nvarchar-代替-char-nchar。"><a href="#27、尽可能使用varchar-nvarchar-代替-char-nchar。" class="headerlink" title="27、尽可能使用varchar/nvarchar 代替 char/nchar。"></a>27、尽可能使用varchar/nvarchar 代替 char/nchar。</h3><p>反例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">`deptName` <span class="type">char</span>(<span class="number">100</span>) <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span> <span class="keyword">COMMENT</span> <span class="string">&#x27;部门名称&#x27;</span></span><br></pre></td></tr></table></figure>

<p>正例：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">`deptName` <span class="type">varchar</span>(<span class="number">100</span>) <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span> <span class="keyword">COMMENT</span> <span class="string">&#x27;部门名称&#x27;</span></span><br></pre></td></tr></table></figure>

<p>理由：</p>
<ul>
<li>因为首先变长字段存储空间小，可以节省存储空间。</li>
<li>其次对于查询来说，在一个相对较小的字段内搜索，效率更高。</li>
</ul>
<h3 id="28、为了提高group-by-语句的效率，可以在执行到该语句前，把不需要的记录过滤掉。"><a href="#28、为了提高group-by-语句的效率，可以在执行到该语句前，把不需要的记录过滤掉。" class="headerlink" title="28、为了提高group by 语句的效率，可以在执行到该语句前，把不需要的记录过滤掉。"></a>28、为了提高group by 语句的效率，可以在执行到该语句前，把不需要的记录过滤掉。</h3><p>反例：</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> job，<span class="built_in">avg</span>（salary） <span class="keyword">from</span> employee  <span class="keyword">group</span> <span class="keyword">by</span> job <span class="keyword">having</span> job =<span class="string">&#x27;president&#x27;</span> <span class="keyword">or</span> job = <span class="string">&#x27;managent&#x27;</span></span><br></pre></td></tr></table></figure>

<p>正例：</p>
<figure class="highlight axapta"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> job，<span class="keyword">avg</span>（salary） <span class="keyword">from</span> employee <span class="keyword">where</span> job =<span class="string">&#x27;president&#x27;</span> or job = <span class="string">&#x27;managent&#x27;</span> <span class="keyword">group</span> <span class="keyword">by</span> job；</span><br></pre></td></tr></table></figure>

<h3 id="29、如果字段类型是字符串，where时一定用引号括起来，否则索引失效"><a href="#29、如果字段类型是字符串，where时一定用引号括起来，否则索引失效" class="headerlink" title="29、如果字段类型是字符串，where时一定用引号括起来，否则索引失效"></a>29、如果字段类型是字符串，where时一定用引号括起来，否则索引失效</h3><p>反例：</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> userid =<span class="number">123</span>;</span><br></pre></td></tr></table></figure>

<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPvyD4fPDXTdMUfegkNnyNdP8QDJrbMIx9HSeSCjp9XMicfD4NM6ZyTLQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">正例：</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> userid =<span class="string">&#x27;123&#x27;</span>;</span><br></pre></td></tr></table></figure>

<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPBvAt3ibwlniaMrZssCsPJ3QrhXW0tzbEMow5Fzov7RSKagxpQt678x0Q/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">理由：</p>
<ul>
<li>为什么第一条语句未加单引号就不走索引了呢？这是因为不加单引号时，是字符串跟数字的比较，它们类型不匹配，MySQL会做隐式的类型转换，把它们转换为浮点数再做比较。</li>
</ul>
<h3 id="30、使用explain-分析你SQL的计划"><a href="#30、使用explain-分析你SQL的计划" class="headerlink" title="30、使用explain 分析你SQL的计划"></a>30、使用explain 分析你SQL的计划</h3><p>日常开发写SQL的时候，尽量养成一个习惯吧。用explain分析一下你写的SQL，尤其是走不走索引这一块。</p>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">explain</span> <span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">user</span> <span class="keyword">where</span> userid =<span class="number">10086</span> <span class="keyword">or</span> age =<span class="number">18</span>;</span><br></pre></td></tr></table></figure>

<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzFY3jrWeG5RQSPS9wh2icScPyibKRjWdCqIgia1UehM2ua0B1n4MtHJgib9sgnhbH6rS5segZSXRMVA9g/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>

    </div>
<div>
  
    <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
    
</div>

  
</div>

    
    
    
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://wan-lei8.gitee.io/2022/03/10/%E4%B9%A6%E5%86%99%E9%AB%98%E8%B4%A8%E9%87%8FSQL%E7%9A%8430%E6%9D%A1%E5%BB%BA%E8%AE%AE/" title="书写高质量SQL的30条建议">https://wan-lei8.gitee.io/2022/03/10/书写高质量SQL的30条建议/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" rel="noopener" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2022/03/10/%E6%B7%B1%E5%88%86%E9%A1%B5%E9%97%AE%E9%A2%98/" rel="prev" title="深分页问题">
      <i class="fa fa-chevron-left"></i> 深分页问题
    </a></div>
      <div class="post-nav-item">
    <a href="/2022/03/22/admin%E5%90%AF%E5%8A%A8%E6%8A%A5%E9%94%99Facade%E6%89%BE%E4%B8%8D%E5%88%B0/" rel="next" title="admin启动报错Facade找不到">
      admin启动报错Facade找不到 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#1%E3%80%81%E6%9F%A5%E8%AF%A2SQL%E5%B0%BD%E9%87%8F%E4%B8%8D%E8%A6%81%E4%BD%BF%E7%94%A8select-%EF%BC%8C%E8%80%8C%E6%98%AFselect%E5%85%B7%E4%BD%93%E5%AD%97%E6%AE%B5%E3%80%82"><span class="nav-number">1.</span> <span class="nav-text">1、查询SQL尽量不要使用select *，而是select具体字段。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2%E3%80%81%E5%A6%82%E6%9E%9C%E7%9F%A5%E9%81%93%E6%9F%A5%E8%AF%A2%E7%BB%93%E6%9E%9C%E5%8F%AA%E6%9C%89%E4%B8%80%E6%9D%A1%E6%88%96%E8%80%85%E5%8F%AA%E8%A6%81%E6%9C%80%E5%A4%A7-%E6%9C%80%E5%B0%8F%E4%B8%80%E6%9D%A1%E8%AE%B0%E5%BD%95%EF%BC%8C%E5%BB%BA%E8%AE%AE%E7%94%A8limit-1"><span class="nav-number">2.</span> <span class="nav-text">2、如果知道查询结果只有一条或者只要最大&#x2F;最小一条记录，建议用limit 1</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3%E3%80%81%E5%BA%94%E5%B0%BD%E9%87%8F%E9%81%BF%E5%85%8D%E5%9C%A8where%E5%AD%90%E5%8F%A5%E4%B8%AD%E4%BD%BF%E7%94%A8or%E6%9D%A5%E8%BF%9E%E6%8E%A5%E6%9D%A1%E4%BB%B6"><span class="nav-number">3.</span> <span class="nav-text">3、应尽量避免在where子句中使用or来连接条件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4%E3%80%81%E4%BC%98%E5%8C%96limit%E5%88%86%E9%A1%B5"><span class="nav-number">4.</span> <span class="nav-text">4、优化limit分页</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5%E3%80%81%E4%BC%98%E5%8C%96%E4%BD%A0%E7%9A%84like%E8%AF%AD%E5%8F%A5"><span class="nav-number">5.</span> <span class="nav-text">5、优化你的like语句</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#6%E3%80%81%E4%BD%BF%E7%94%A8where%E6%9D%A1%E4%BB%B6%E9%99%90%E5%AE%9A%E8%A6%81%E6%9F%A5%E8%AF%A2%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E9%81%BF%E5%85%8D%E8%BF%94%E5%9B%9E%E5%A4%9A%E4%BD%99%E7%9A%84%E8%A1%8C"><span class="nav-number">6.</span> <span class="nav-text">6、使用where条件限定要查询的数据，避免返回多余的行</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#7%E3%80%81%E5%B0%BD%E9%87%8F%E9%81%BF%E5%85%8D%E5%9C%A8%E7%B4%A2%E5%BC%95%E5%88%97%E4%B8%8A%E4%BD%BF%E7%94%A8mysql%E7%9A%84%E5%86%85%E7%BD%AE%E5%87%BD%E6%95%B0"><span class="nav-number">7.</span> <span class="nav-text">7、尽量避免在索引列上使用mysql的内置函数</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#8%E3%80%81%E5%BA%94%E5%B0%BD%E9%87%8F%E9%81%BF%E5%85%8D%E5%9C%A8where%E5%AD%90%E5%8F%A5%E4%B8%AD%E5%AF%B9%E5%AD%97%E6%AE%B5%E8%BF%9B%E8%A1%8C%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%93%8D%E4%BD%9C%EF%BC%8C%E8%BF%99%E5%B0%86%E5%AF%BC%E8%87%B4%E7%B3%BB%E7%BB%9F%E6%94%BE%E5%BC%83%E4%BD%BF%E7%94%A8%E7%B4%A2%E5%BC%95%E8%80%8C%E8%BF%9B%E8%A1%8C%E5%85%A8%E8%A1%A8%E6%89%AB"><span class="nav-number">8.</span> <span class="nav-text">8、应尽量避免在where子句中对字段进行表达式操作，这将导致系统放弃使用索引而进行全表扫</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#9%E3%80%81Inner-join-%E3%80%81left-join%E3%80%81right-join%EF%BC%8C%E4%BC%98%E5%85%88%E4%BD%BF%E7%94%A8Inner-join%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%98%AFleft-join%EF%BC%8C%E5%B7%A6%E8%BE%B9%E8%A1%A8%E7%BB%93%E6%9E%9C%E5%B0%BD%E9%87%8F%E5%B0%8F"><span class="nav-number">9.</span> <span class="nav-text">9、Inner join 、left join、right join，优先使用Inner join，如果是left join，左边表结果尽量小</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#10%E3%80%81%E5%BA%94%E5%B0%BD%E9%87%8F%E9%81%BF%E5%85%8D%E5%9C%A8where%E5%AD%90%E5%8F%A5%E4%B8%AD%E4%BD%BF%E7%94%A8-%E6%88%96-lt-gt-%E6%93%8D%E4%BD%9C%E7%AC%A6%EF%BC%8C%E5%90%A6%E5%88%99%E5%B0%86%E5%BC%95%E6%93%8E%E6%94%BE%E5%BC%83%E4%BD%BF%E7%94%A8%E7%B4%A2%E5%BC%95%E8%80%8C%E8%BF%9B%E8%A1%8C%E5%85%A8%E8%A1%A8%E6%89%AB%E6%8F%8F%E3%80%82"><span class="nav-number">10.</span> <span class="nav-text">10、应尽量避免在where子句中使用!&#x3D;或&lt;&gt;操作符，否则将引擎放弃使用索引而进行全表扫描。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#11%E3%80%81%E4%BD%BF%E7%94%A8%E8%81%94%E5%90%88%E7%B4%A2%E5%BC%95%E6%97%B6%EF%BC%8C%E6%B3%A8%E6%84%8F%E7%B4%A2%E5%BC%95%E5%88%97%E7%9A%84%E9%A1%BA%E5%BA%8F%EF%BC%8C%E4%B8%80%E8%88%AC%E9%81%B5%E5%BE%AA%E6%9C%80%E5%B7%A6%E5%8C%B9%E9%85%8D%E5%8E%9F%E5%88%99%E3%80%82"><span class="nav-number">11.</span> <span class="nav-text">11、使用联合索引时，注意索引列的顺序，一般遵循最左匹配原则。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#12%E3%80%81%E5%AF%B9%E6%9F%A5%E8%AF%A2%E8%BF%9B%E8%A1%8C%E4%BC%98%E5%8C%96%EF%BC%8C%E5%BA%94%E8%80%83%E8%99%91%E5%9C%A8where%E5%8F%8Aorder-by%E6%B6%89%E5%8F%8A%E7%9A%84%E5%88%97%E4%B8%8A%E5%BB%BA%E7%AB%8B%E7%B4%A2%E5%BC%95%EF%BC%8C%E5%B0%BD%E9%87%8F%E9%81%BF%E5%85%8D%E5%85%A8%E8%A1%A8%E6%89%AB%E6%8F%8F%E3%80%82"><span class="nav-number">12.</span> <span class="nav-text">12、对查询进行优化，应考虑在where及order by涉及的列上建立索引，尽量避免全表扫描。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#13%E3%80%81%E5%A6%82%E6%9E%9C%E6%8F%92%E5%85%A5%E6%95%B0%E6%8D%AE%E8%BF%87%E5%A4%9A%EF%BC%8C%E8%80%83%E8%99%91%E6%89%B9%E9%87%8F%E6%8F%92%E5%85%A5%E3%80%82"><span class="nav-number">13.</span> <span class="nav-text">13、如果插入数据过多，考虑批量插入。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#14%E3%80%81%E5%9C%A8%E9%80%82%E5%BD%93%E7%9A%84%E6%97%B6%E5%80%99%EF%BC%8C%E4%BD%BF%E7%94%A8%E8%A6%86%E7%9B%96%E7%B4%A2%E5%BC%95%E3%80%82"><span class="nav-number">14.</span> <span class="nav-text">14、在适当的时候，使用覆盖索引。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#15%E3%80%81%E6%85%8E%E7%94%A8distinct%E5%85%B3%E9%94%AE%E5%AD%97"><span class="nav-number">15.</span> <span class="nav-text">15、慎用distinct关键字</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#16%E3%80%81%E5%88%A0%E9%99%A4%E5%86%97%E4%BD%99%E5%92%8C%E9%87%8D%E5%A4%8D%E7%B4%A2%E5%BC%95"><span class="nav-number">16.</span> <span class="nav-text">16、删除冗余和重复索引</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#17%E3%80%81%E5%A6%82%E6%9E%9C%E6%95%B0%E6%8D%AE%E9%87%8F%E8%BE%83%E5%A4%A7%EF%BC%8C%E4%BC%98%E5%8C%96%E4%BD%A0%E7%9A%84%E4%BF%AE%E6%94%B9-%E5%88%A0%E9%99%A4%E8%AF%AD%E5%8F%A5%E3%80%82"><span class="nav-number">17.</span> <span class="nav-text">17、如果数据量较大，优化你的修改&#x2F;删除语句。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#18%E3%80%81where%E5%AD%90%E5%8F%A5%E4%B8%AD%E8%80%83%E8%99%91%E4%BD%BF%E7%94%A8%E9%BB%98%E8%AE%A4%E5%80%BC%E4%BB%A3%E6%9B%BFnull%E3%80%82"><span class="nav-number">18.</span> <span class="nav-text">18、where子句中考虑使用默认值代替null。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link"><span class="nav-number">19.</span> <span class="nav-text"></span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%A6%82%E6%9E%9C%E6%8A%8Anull%E5%80%BC%EF%BC%8C%E6%8D%A2%E6%88%90%E9%BB%98%E8%AE%A4%E5%80%BC%EF%BC%8C%E5%BE%88%E5%A4%9A%E6%97%B6%E5%80%99%E8%AE%A9%E8%B5%B0%E7%B4%A2%E5%BC%95%E6%88%90%E4%B8%BA%E5%8F%AF%E8%83%BD%EF%BC%8C%E5%90%8C%E6%97%B6%EF%BC%8C%E8%A1%A8%E8%BE%BE%E6%84%8F%E6%80%9D%E4%BC%9A%E7%9B%B8%E5%AF%B9%E6%B8%85%E6%99%B0%E4%B8%80%E7%82%B9%E3%80%82"><span class="nav-number">20.</span> <span class="nav-text">如果把null值，换成默认值，很多时候让走索引成为可能，同时，表达意思会相对清晰一点。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#19%E3%80%81%E4%B8%8D%E8%A6%81%E6%9C%89%E8%B6%85%E8%BF%875%E4%B8%AA%E4%BB%A5%E4%B8%8A%E7%9A%84%E8%A1%A8%E8%BF%9E%E6%8E%A5"><span class="nav-number">21.</span> <span class="nav-text">19、不要有超过5个以上的表连接</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#20%E3%80%81exist-amp-in%E7%9A%84%E5%90%88%E7%90%86%E5%88%A9%E7%94%A8"><span class="nav-number">22.</span> <span class="nav-text">20、exist&amp;in的合理利用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#21%E3%80%81%E5%B0%BD%E9%87%8F%E7%94%A8union-all%E6%9B%BF%E6%8D%A2-union"><span class="nav-number">23.</span> <span class="nav-text">21、尽量用union all替换 union</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#22%E3%80%81%E7%B4%A2%E5%BC%95%E4%B8%8D%E5%AE%9C%E5%A4%AA%E5%A4%9A%EF%BC%8C%E4%B8%80%E8%88%AC5%E4%B8%AA%E4%BB%A5%E5%86%85%E3%80%82"><span class="nav-number">24.</span> <span class="nav-text">22、索引不宜太多，一般5个以内。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#23%E3%80%81%E5%B0%BD%E9%87%8F%E4%BD%BF%E7%94%A8%E6%95%B0%E5%AD%97%E5%9E%8B%E5%AD%97%E6%AE%B5%EF%BC%8C%E8%8B%A5%E5%8F%AA%E5%90%AB%E6%95%B0%E5%80%BC%E4%BF%A1%E6%81%AF%E7%9A%84%E5%AD%97%E6%AE%B5%E5%B0%BD%E9%87%8F%E4%B8%8D%E8%A6%81%E8%AE%BE%E8%AE%A1%E4%B8%BA%E5%AD%97%E7%AC%A6%E5%9E%8B"><span class="nav-number">25.</span> <span class="nav-text">23、尽量使用数字型字段，若只含数值信息的字段尽量不要设计为字符型</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#24%E3%80%81%E7%B4%A2%E5%BC%95%E4%B8%8D%E9%80%82%E5%90%88%E5%BB%BA%E5%9C%A8%E6%9C%89%E5%A4%A7%E9%87%8F%E9%87%8D%E5%A4%8D%E6%95%B0%E6%8D%AE%E7%9A%84%E5%AD%97%E6%AE%B5%E4%B8%8A%EF%BC%8C%E5%A6%82%E6%80%A7%E5%88%AB%E8%BF%99%E7%B1%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E5%BA%93%E5%AD%97%E6%AE%B5%E3%80%82"><span class="nav-number">26.</span> <span class="nav-text">24、索引不适合建在有大量重复数据的字段上，如性别这类型数据库字段。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#25%E3%80%81%E5%B0%BD%E9%87%8F%E9%81%BF%E5%85%8D%E5%90%91%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%BF%94%E5%9B%9E%E8%BF%87%E5%A4%9A%E6%95%B0%E6%8D%AE%E9%87%8F%E3%80%82"><span class="nav-number">27.</span> <span class="nav-text">25、尽量避免向客户端返回过多数据量。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#26%E3%80%81%E5%BD%93%E5%9C%A8SQL%E8%AF%AD%E5%8F%A5%E4%B8%AD%E8%BF%9E%E6%8E%A5%E5%A4%9A%E4%B8%AA%E8%A1%A8%E6%97%B6-%E8%AF%B7%E4%BD%BF%E7%94%A8%E8%A1%A8%E7%9A%84%E5%88%AB%E5%90%8D%EF%BC%8C%E5%B9%B6%E6%8A%8A%E5%88%AB%E5%90%8D%E5%89%8D%E7%BC%80%E4%BA%8E%E6%AF%8F%E4%B8%80%E5%88%97%E4%B8%8A%EF%BC%8C%E8%BF%99%E6%A0%B7%E8%AF%AD%E4%B9%89%E6%9B%B4%E5%8A%A0%E6%B8%85%E6%99%B0%E3%80%82"><span class="nav-number">28.</span> <span class="nav-text">26、当在SQL语句中连接多个表时,请使用表的别名，并把别名前缀于每一列上，这样语义更加清晰。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#27%E3%80%81%E5%B0%BD%E5%8F%AF%E8%83%BD%E4%BD%BF%E7%94%A8varchar-nvarchar-%E4%BB%A3%E6%9B%BF-char-nchar%E3%80%82"><span class="nav-number">29.</span> <span class="nav-text">27、尽可能使用varchar&#x2F;nvarchar 代替 char&#x2F;nchar。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#28%E3%80%81%E4%B8%BA%E4%BA%86%E6%8F%90%E9%AB%98group-by-%E8%AF%AD%E5%8F%A5%E7%9A%84%E6%95%88%E7%8E%87%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%9C%A8%E6%89%A7%E8%A1%8C%E5%88%B0%E8%AF%A5%E8%AF%AD%E5%8F%A5%E5%89%8D%EF%BC%8C%E6%8A%8A%E4%B8%8D%E9%9C%80%E8%A6%81%E7%9A%84%E8%AE%B0%E5%BD%95%E8%BF%87%E6%BB%A4%E6%8E%89%E3%80%82"><span class="nav-number">30.</span> <span class="nav-text">28、为了提高group by 语句的效率，可以在执行到该语句前，把不需要的记录过滤掉。</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#29%E3%80%81%E5%A6%82%E6%9E%9C%E5%AD%97%E6%AE%B5%E7%B1%BB%E5%9E%8B%E6%98%AF%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%8Cwhere%E6%97%B6%E4%B8%80%E5%AE%9A%E7%94%A8%E5%BC%95%E5%8F%B7%E6%8B%AC%E8%B5%B7%E6%9D%A5%EF%BC%8C%E5%90%A6%E5%88%99%E7%B4%A2%E5%BC%95%E5%A4%B1%E6%95%88"><span class="nav-number">31.</span> <span class="nav-text">29、如果字段类型是字符串，where时一定用引号括起来，否则索引失效</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#30%E3%80%81%E4%BD%BF%E7%94%A8explain-%E5%88%86%E6%9E%90%E4%BD%A0SQL%E7%9A%84%E8%AE%A1%E5%88%92"><span class="nav-number">32.</span> <span class="nav-text">30、使用explain 分析你SQL的计划</span></a></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt=""
      src="/images/avatar.png">
  <p class="site-author-name" itemprop="name"></p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives">
          <span class="site-state-item-count">41</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/yourname" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;yourname" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="/malegod958@163.com" title="E-Mail → malegod958@163.com"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>
  <div class="cc-license motion-element" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 2018 – 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">万磊</span>
</div>
  <div class="powered-by">

  </div>

        








      </div>
    </footer>
  </div>

  
  
  <script color='' opacity='0.5' zIndex='-1' count='99' src="/lib/canvas-nest/canvas-nest.min.js"></script>
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

  
	<script type="text/javascript" src="//cdn.bootcss.com/canvas-nest.js/1.0.0/canvas-nest.min.js"></script>
	

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body>
</html>
<!-- 页面点击小红心 -->
<script type="text/javascript" src="/js/src/clicklove.js"></script>
